package com.smsc.headend.connector.netty.decoder;

import cn.hutool.core.util.StrUtil;
import com.smsc.headend.connector.utils.NetUtil;
import com.smsc.headend.module.protocol.cosem.util.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.netty.util.ReferenceCountUtil;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

public class DecodeProxy extends ByteToMessageDecoder {

    private Logger logger = LoggerFactory.getLogger(DecodeProxy.class);

    private static AtomicInteger tcpConnected = new AtomicInteger(0);
    /**
     * 保存客户端IP
     */
    public static final AttributeKey<String> key = AttributeKey.valueOf("IP");

    /**
     * decode() 会根据接收的数据，被调用多次，直到确定没有新的元素添加到list,
     * 或者是 ByteBuf 没有更多的可读字节为止。
     * 如果 list 不为空，就会将 list 的内容传递给下一个 handler
     *
     * @param ctx     上下文对象
     * @param byteBuf 入站后的 ByteBuf
     * @param out     将解码后的数据传递给下一个 handler
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
        byte[] bytes = printSz(ctx, byteBuf);

        String ipSet = ctx.channel().attr(key).get();

        // logger.info("从客户端收到的字符串:" + message);
        if (bytes.length > 0 && StringUtils.isEmpty(ipSet)) {
            //判断是否有代理
            String message = new String(bytes, Charset.forName("UTF-8"));
            if (message.indexOf("PROXY") == 0) {
                //PROXY TCP4 101.106.236.66 192.168.0.150 12646 5683\r\n
                // logger.info("PROXY MSG: " + message.substring(0,message.length()-2));
                if (message.indexOf('\n') != -1) {
                    final String[] clientIP = {null};
                    AtomicInteger temp = new AtomicInteger();
                    Stream.of(message.split("\n")).filter(
                            msg -> {
                                Boolean flag = msg.indexOf("PROXY") >= 0;
                                if (flag) {
                                    temp.addAndGet(msg.length() + 1);
                                }
                                return flag;
                            }
                    ).forEach(
                            protocolMsg -> {
                                String[] str = protocolMsg.split(" ");
                                String ip = str[2] + ":" + str[4];
                                int i = tcpConnected.incrementAndGet();
                                logger.info("ProxyProtocolClientIP: {}, count:{}, channelIp:{}", ip, i, NetUtil.getIpFromChannel(ctx.channel()));
                                clientIP[0] = ip;
                            }
                    );
                    Attribute<String> channelAttr = ctx.channel().attr(key);
                    //基于channel的属性
                    if (null == channelAttr.get()) {
                        channelAttr.set(clientIP[0]);
                    }
                    //标记Proxy Protocol信息已被读取， 输出后续报文
                    byteBuf.readBytes(temp.get());
                }
            }
        }

        if (byteBuf.readableBytes() > 0) {
            out.add(byteBuf.readBytes(byteBuf.readableBytes()));
        }
    }


    /**
     * 打印byte数组
     * @param ctx
     * @param newBuf
     */
    public byte[] printSz(ChannelHandlerContext ctx, ByteBuf newBuf) {
        ByteBuf copy = newBuf.copy();
        byte[] bytes = new byte[copy.readableBytes()];
        copy.readBytes(bytes);
        logger.trace("{}: decodeProxy {}", NetUtil.getIpFromChannel(ctx.channel()), ByteUtils.byteToHexString(bytes));
        ReferenceCountUtil.release(copy);
        return bytes;
    }
}
